
#include <cmath>
#include <BOpenGL>
#include "IGlobal.h"
#include "member_BPainter.h"
#include "member_BStyle.h"

using namespace BWE;

member_BPainter::member_BPainter(BPainter* painter)
{
	boss = painter;
	widget = 0;
	pixmap = 0;
	graphic = 0;

	tbo = 0;
	style = 0;
	font = 0;
	program = 0;
	scale = 1;
	cullback = glIsEnabled(GL_CULL_FACE);
	polySmooth = glIsEnabled(GL_MULTISAMPLE);
	lineSmooth = glIsEnabled(GL_LINE_SMOOTH);
	pointSmooth = glIsEnabled(GL_POINT_SMOOTH);
	glGetFloatv(GL_POINT_SIZE, &pointSize);
	glGetFloatv(GL_LINE_WIDTH, &lineWidth);
	glGetIntegerv(GL_LINE_STIPPLE, &lineStipple);
}
member_BPainter::~member_BPainter()
{

}

const BColor* member_BPainter::findColor(int name)
{
	if (name > 0)
	{
		if (style)
		{
			auto it = style_member(style)->colorMap.find(name);
			if (it.valid())
				return &(*it);
		}
		else if (state.style)
		{
			auto it = style_member(state.style)->colorMap.find(name);
			if (it.valid())
				return &(*it);
		}
		auto it = style_member(app_style)->colorMap.find(name);
		if (it.valid())
			return &(*it);
	}
	return 0;
}
const BColor* member_BPainter::findColor(const char* name)
{
	if (name)
	{
		if (style)
		{
			auto it = style_member(style)->namedColorMap.find(name);
			if (it.valid())
				return &(*it);
		}
		else if (state.style)
		{
			auto it = style_member(state.style)->namedColorMap.find(name);
			if (it.valid())
				return &(*it);
		}
		auto it = style_member(app_style)->namedColorMap.find(name);
		if (it.valid())
			return &(*it);
	}
	return 0;
}
const BColor* member_BPainter::findColor(const BString& name)
{
	if (name.size())
	{
		if (style)
		{
			auto it = style_member(style)->namedColorMap.find(name);
			if (it.valid())
				return &(*it);
		}
		else if (state.style)
		{
			auto it = style_member(state.style)->namedColorMap.find(name);
			if (it.valid())
				return &(*it);
		}
		auto it = style_member(app_style)->namedColorMap.find(name);
		if (it.valid())
			return &(*it);
	}
	return 0;
}

const BImage* member_BPainter::findImage(int name)
{
	if (name > 0)
	{
		if (style)
		{
			auto it = style_member(style)->imageMap.find(name);
			if (it.valid())
				return *it;
		}
		else if (state.style)
		{
			auto it = style_member(state.style)->imageMap.find(name);
			if (it.valid())
				return *it;
		}
		auto it = style_member(app_style)->imageMap.find(name);
		if (it.valid())
			return *it;
	}
	return 0;
}
const BImage* member_BPainter::findImage(const char* name)
{
	if (name)
	{
		if (style)
		{
			auto it = style_member(style)->namedImageMap.find(name);
			if (it.valid())
				return *it;
		}
		else if (state.style)
		{
			auto it = style_member(state.style)->namedImageMap.find(name);
			if (it.valid())
				return *it;
		}
		auto it = style_member(app_style)->namedImageMap.find(name);
		if (it.valid())
			return *it;
	}
	return 0;
}
const BImage* member_BPainter::findImage(const BString& name)
{
	if (name.size())
	{
		if (style)
		{
			auto it = style_member(style)->namedImageMap.find(name);
			if (it.valid())
				return *it;
		}
		else if (state.style)
		{
			auto it = style_member(state.style)->namedImageMap.find(name);
			if (it.valid())
				return *it;
		}
		auto it = style_member(app_style)->namedImageMap.find(name);
		if (it.valid())
			return *it;
	}
	return 0;
}

void member_BPainter::createPoints(const BRectf& rect, float rx, float ry)
{
	float halfPI = PIf * 0.5f;
	floatPoints.reset();
	if (rx <= 0 || ry <= 0)
	{
		floatPoints.append(rect.leftTop());
		floatPoints.append(rect.leftBottom());
		floatPoints.append(rect.rightBottom());
		floatPoints.append(rect.rightTop());
		return;
	}
	//create left top points
	{
		BPointf center(rect.left() + rx, rect.top() + ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			float sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				float angle = PIf - i * sr;
				float x = cos(angle) * rx;
				float y = sin(angle) * rx;
				floatPoints.append(center + BPointf(x, -y));
			}
		}
		else
		{
			float rx2 = rx * rx;
			float ry2 = ry * ry;
			for (float x = -rx; x < 0; x += 2)
			{
				float y = sqrt((1.0f - (x * x) / rx2) * ry2);
				floatPoints.append(center + BPointf(x, -y));
			}
			floatPoints.append(center + BPointf(0, -ry));
		}
	}
	//create right top points
	{
		BPointf center(rect.right() - rx, rect.top() + ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			float sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				float angle = halfPI - i * sr;
				float x = cos(angle) * rx;
				float y = sin(angle) * rx;
				floatPoints.append(center + BPointf(x, -y));
			}
		}
		else
		{
			float rx2 = rx * rx;
			float ry2 = ry * ry;
			for (float x = 0; x < rx; x += 2)
			{
				float y = sqrt((1.0f - (x * x) / rx2) * ry2);
				floatPoints.append(center + BPointf(x, -y));
			}
			floatPoints.append(center + BPointf(rx, 0));
		}
	}
	//create right bottom points
	{
		BPointf center(rect.right() - rx, rect.bottom() - ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			float sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				float angle = -i * sr;
				float x = cos(angle) * rx;
				float y = sin(angle) * rx;
				floatPoints.append(center + BPointf(x, -y));
			}
		}
		else
		{
			float rx2 = rx * rx;
			float ry2 = ry * ry;
			for (float x = rx; x > 0; x -= 2)
			{
				float y = sqrt((1 - (x * x) / rx2) * ry2);
				floatPoints.append(center + BPointf(x, y));
			}
			floatPoints.append(center + BPointf(0, ry));
		}
	}
	//create left bottom points
	{
		BPointf center(rect.left() + rx, rect.bottom() - ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			float sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				float angle = -(halfPI + i * sr);
				float x = cos(angle) * rx;
				float y = sin(angle) * rx;
				floatPoints.append(center + BPointf(x, -y));
			}
		}
		else
		{
			float rx2 = rx * rx;
			float ry2 = ry * ry;
			for (float x = 0; x > -rx; x -= 2)
			{
				float y = sqrt((1 - (x * x) / rx2) * ry2);
				floatPoints.append(center + BPointf(x, y));
			}
			floatPoints.append(center + BPointf(-rx, 0));
		}
	}
}
void member_BPainter::createPoints(const BRectd& rect, double rx, double ry)
{
	double halfPI = PI * 0.5;
	doublePoints.reset();
	if (rx <= 0 || ry <= 0)
	{
		doublePoints.append(rect.leftTop());
		doublePoints.append(rect.leftBottom());
		doublePoints.append(rect.rightBottom());
		doublePoints.append(rect.rightTop());
		return;
	}
	//create left top points
	{
		BPointd center(rect.left() + rx, rect.top() + ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			double sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				double angle = PIf - i * sr;
				double x = cos(angle) * rx;
				double y = sin(angle) * rx;
				doublePoints.append(center + BPointd(x, -y));
			}
		}
		else
		{
			double rx2 = rx * rx;
			double ry2 = ry * ry;
			for (double x = -rx; x < 0; x += 2)
			{
				double y = sqrt((1.0 - (x * x) / rx2) * ry2);
				doublePoints.append(center + BPointd(x, -y));
			}
			doublePoints.append(center + BPointd(0.0, -ry));
		}
	}
	//create right top points
	{
		BPointd center(rect.right() - rx, rect.top() + ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			double sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				double angle = halfPI - i * sr;
				double x = cos(angle) * rx;
				double y = sin(angle) * rx;
				doublePoints.append(center + BPointd(x, -y));
			}
		}
		else
		{
			double rx2 = rx * rx;
			double ry2 = ry * ry;
			for (double x = 0; x < rx; x += 2)
			{
				double y = sqrt((1.0f - (x * x) / rx2) * ry2);
				doublePoints.append(center + BPointd(x, -y));
			}
			doublePoints.append(center + BPointd(rx, 0.0));
		}
	}
	//create right bottom points
	{
		BPointd center(rect.right() - rx, rect.bottom() - ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			double sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				double angle = -i * sr;
				double x = cos(angle) * rx;
				double y = sin(angle) * rx;
				doublePoints.append(center + BPointd(x, -y));
			}
		}
		else
		{
			double rx2 = rx * rx;
			double ry2 = ry * ry;
			for (double x = rx; x > 0; x -= 2.0)
			{
				double y = sqrt((1 - (x * x) / rx2) * ry2);
				doublePoints.append(center + BPointd(x, y));
			}
			doublePoints.append(center + BPointd(0, ry));
		}
	}
	//create left bottom points
	{
		BPointd center(rect.left() + rx, rect.bottom() - ry);
		if (rx == ry)
		{
			int sides = (int)bClamp(rx / 3, 3, 24);
			double sr = halfPI / sides;
			for (int i = 0; i <= sides; i++)
			{
				double angle = -(halfPI + i * sr);
				double x = cos(angle) * rx;
				double y = sin(angle) * rx;
				doublePoints.append(center + BPointd(x, -y));
			}
		}
		else
		{
			double rx2 = rx * rx;
			double ry2 = ry * ry;
			for (double x = 0; x > -rx; x -= 2.0)
			{
				double y = sqrt((1 - (x * x) / rx2) * ry2);
				doublePoints.append(center + BPointd(x, y));
			}
			doublePoints.append(center + BPointd(-rx, 0));
		}
	}
}
